import {
  type ParentComponent,
  Show,
  createMemo,
  mergeProps,
  splitProps,
} from "solid-js";
import type { JSX } from "solid-js/jsx-runtime";

export interface CheckBoxProps
  extends JSX.CustomAttributes<HTMLInputElement>,
    Omit<
      JSX.InputHTMLAttributes<HTMLInputElement>,
      "value" | "onChange" | "disabled" | "type"
    > {
  value?: boolean;
  onChange?: (value: boolean) => void;
  disabled?: boolean;
  inline?: boolean;
  reverse?: boolean;
  type?: "checkbox" | "radio" | "switch";
  wrapWithForm?: boolean;
}

const CheckBoxDefaultProps: Partial<CheckBoxProps> = {
  value: false,
  disabled: false,
  inline: false,
  reverse: false,
  type: "checkbox",
};

const RadioBoxDefaultProps: Partial<CheckBoxProps> = {
  value: false,
  disabled: false,
  inline: false,
  reverse: false,
  type: "radio",
};

const SwitchBoxDefaultProps: Partial<CheckBoxProps> = {
  value: false,
  disabled: false,
  inline: false,
  reverse: false,
  type: "switch",
};

const BasicCheckBox: ParentComponent<CheckBoxProps> = (p) => {
  const [local, attributes] = splitProps(mergeProps(CheckBoxDefaultProps, p), [
    "type",
    "wrapWithForm",
    "inline",
    "reverse",
    "type",
    "classList",
    "onChange",
    "value",
    "disabled",
    "children",
    "ref",
    "$ServerOnly",
  ]);

  const innerClassList = createMemo(() => {
    return {
      ...local.classList,
      "form-check-input": local.wrapWithForm,
      "form-chcek-inline": local.inline,
      "form-check-reverse": local.reverse,
      "form-switch": local.type === "switch",
    };
  });
  const innerType = createMemo(() => {
    if (local.type === "switch") {
      return "checkbox";
    }
    return local.type;
  });

  const handleChanged: JSX.InputHTMLAttributes<HTMLInputElement>["onChange"] = (
    e
  ) => {
    // console.log("changed", e);
    local.onChange?.(e.currentTarget.checked);
  };

  const control = (
    <>
      <input
        ref={local.ref}
        type={innerType()}
        checked={local.value}
        onChange={handleChanged}
        disabled={local.disabled}
        classList={innerClassList()}
        {...attributes}
      ></input>
      <Show when={local.children}>{local.children}</Show>
    </>
  );

  return p.wrapWithForm ? <div class="form-check">{control}</div> : control;
};

export const RadioBox: ParentComponent<Omit<CheckBoxProps, "type">> = (p) => {
  const props = mergeProps(RadioBoxDefaultProps, p);
  return <BasicCheckBox {...props}></BasicCheckBox>;
};

export const SwtichBox: ParentComponent<Omit<CheckBoxProps, "type">> = (p) => {
  const props = mergeProps(SwitchBoxDefaultProps, p);
  return <BasicCheckBox {...props}></BasicCheckBox>;
};

type CheckBoxType = typeof BasicCheckBox & {
  Radio: typeof RadioBox;
  Switch: typeof SwtichBox;
};

const CheckBox = BasicCheckBox as CheckBoxType;

CheckBox.Radio = RadioBox;
CheckBox.Switch = SwtichBox;

export default CheckBox;
